﻿/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is [eden: ECMAScript data exchange notation AS3]. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2004-2011
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
  Marc Alcaraz <ekameleon@gmail.com>.
  
*/

package library.eden
{
    import core.dump;
    import core.filedump;
    
    /**
     * The eden Serializer class
     */
    public class EdenSerializer
    {
        private var _cached:ECMAScript;
        private var _current:ECMAScript;
        
        private var _aliases:Object = {};
        
        /** Creates a new EdenSerializer instance. */
        public function EdenSerializer()
        {
            /* note:
               later we may want to configure the instanciation of the serializer
               ex: custom config, custom authorized etc.
            */
        }
        
        /** The config reference of the eden serializer. */
        public function get config():EdenConfigurator { return metadata.config; }
        
        /** Returns the last parser session logs */
        public function get logs():Array
        {
            if( _current ) 
            { 
                return _current.logs; 
            }
            return [];
        }
        
        /** Returns the last parser session comments */
        public function get comments():String
        {
            if( _current ) { return _current.comments; }
            return "";
        }
        
        /** Inserts a new alias. */
        public function addAlias( alias:String , value:String ):void { _aliases[ alias ] = value; }
        
        /**
         * Inserts an authorized path in the white list of the parser.
         */
        public function addAuthorized( ...arguments:Array ):void
        {
            var l:int = arguments.length;
            if( l > 0 )
            { 
                if( !metadata.config.authorized ) { metadata.config.authorized = []; }
                var a:Array = metadata.config.authorized;
                if( a )
                {
                    for( var i:int = 0 ; i < l ; i++ )
                    {
                        if( ! a.indexOf( arguments[i] ) > - 1 ) { a.push( arguments[i] ); }
                    }
                }
                else { throw new Error( metadata.strings.addAuthorizedFailed ); }
            }
        }
        
        /** Remove all the aliases. */
        public function clearAlias():void { _aliases = {}; }
        
        private function _buildAliases():String
        {
            var EOL:String = ";";
            var aliases:Array = [];
            var member:String;
            for( member in _aliases )
            {
                aliases.push( member + " = " + _aliases[member] + EOL );
            }
            return aliases.join( "\n" );
        }
        
        /**
         * Parse a string and interpret the source code to the correct ECMAScript construct.
         * <p><b>Example :</b></p>
         * <pre class="prettyprint">
         * "undefined" --> undefined
         * "0xFF"      --> 255
         * "{a:1,b:2}" --> {a:1,b:2}
         * </pre>
         * @param source     string source to interpret
         * @param useCaching allow to cache the parser and reuse its object pool
         * @return an ECMAScript construct
         */
        public function deserialize( source:String, useCaching:Boolean = false ):*
        {
            if( !_cached ) { _cached = new ECMAScript( "" ); }
            
            source = _buildAliases() + source;
            
            if( useCaching )
            {
                _cached.enableErrorChecking = metadata.config.enableErrorChecking;
                _cached.load( source );
                _current = _cached;
                return _cached.eval();
            }
            
            _current = new ECMAScript( source, metadata.config.enableErrorChecking );
            return _current.eval();
        }
        
        /**
         * Removes an authorized path in the white list of the parser.
         */
        public function removeAuthorized( ...arguments:Array ):void
        {
            if( !metadata.config.authorized ) { return; }
            var paths:*;
            var i:int;
            var found:*;
            paths = [].concat( arguments );
            var l:int = paths.length;
            for( i = 0 ; i < l ; i++ )
            {
                found = metadata.config.authorized.indexOf( paths[i] );
                if( found > - 1 ) { metadata.config.authorized.splice( found, 1 ); }
            }
        }
        
        /** Serialize the specified value object passed-in argument. */
        public function serialize( value:*, prettyPrint:Boolean = false ):String { return dump( value, prettyPrint ); }
        
        /** Serialize for file the specified value object passed-in argument. */
        public function serializeForFile( value:* ):String { return filedump( value ); }
        
        /** Returns the string representation of the object. */
        public function toString():String { return metadata.name + " v"+metadata.version; }
        
    }
}